package cn.jiangzeyin.job;

import cn.jiangzeyin.entity.IQuartzInfo;
import cn.jiangzeyin.entity.JobRunResultStatus;
import cn.jiangzeyin.system.JobDataUtil;
import cn.jiangzeyin.system.JobPropertiesInfo;
import cn.jiangzeyin.system.SystemJobManager;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.PersistJobDataAfterExecution;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 调度类
 * <p>
 * 异常后保存JobData
 * <p>
 * <p>
 * 不允许并发执行
 *
 * @author jiangzeyin
 */
@PersistJobDataAfterExecution
@DisallowConcurrentExecution
public abstract class BaseJob implements Job {
    /**
     * 运行状态
     */
    private static final ConcurrentHashMap<String, JobRunResultStatus> JOB_RUN_RESULT_STATUS_CONCURRENT_HASH_MAP = new ConcurrentHashMap<>();

    /**
     * 当前调度对象
     */
    protected JobExecutionContext context;
    private HashMap<String, String> jobData = new HashMap<>();
    private Class entityClass;

    /**
     * 默认调度执行
     *
     * @param context context
     * @author jiangzeyin
     */
    @Override
    public void execute(JobExecutionContext context) {
        // TODO Auto-generated method stub
        this.execute(context, JobDataUtil.getInstance().getJobDefaultClass());
    }

    /**
     * 自定义调用运行数据类
     *
     * @param context     context
     * @param entityClass 运行数据对应实体
     */
    public void execute(JobExecutionContext context, Class entityClass) {
        if (entityClass == null) {
            throw new IllegalArgumentException("entityClass is null");
        }
        this.context = context;
        this.entityClass = entityClass;
        int jobId = getJobId();
        if (jobId > 0) {
            JSONArray jsonArray = JobDataUtil.getInstance().getJobRunData(entityClass, jobId);
            for (int i = jsonArray == null ? -1 : jsonArray.size() - 1; i > -1; i--) {
                JSONObject jsonObject = jsonArray.getJSONObject(i);
                jobData.put(jsonObject.getString(SystemJobManager.RunData.getKeyName()), jsonObject.getString(SystemJobManager.RunData.getValueName()));
            }
        }
        putStatus(false);
    }

    /**
     * @param name  name
     * @param value value
     */
    public synchronized void saveRunDataValue(String name, Object value) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put(name, value);
        saveRunDataValue(jsonObject);
    }

    /**
     * 保存运行数据
     *
     * @param jsonObject json
     * @author jiangzeyin
     */
    public synchronized void saveRunDataValue(JSONObject jsonObject) {
        if (jsonObject == null) {
            return;
        }
        JSONArray jsonArray = JobDataUtil.getInstance().getJobRunData(entityClass, getJobId());
        if (jsonArray == null) {
            jsonArray = new JSONArray();
        }
        Set<Map.Entry<String, Object>> entries = jsonObject.entrySet();
        for (Map.Entry<String, Object> item : entries) {
            if (item == null) {
                continue;
            }
            String keyName = item.getKey();
            boolean isFind = false;
            if (keyName != null) {
                for (int i = 0; i < jsonArray.size(); i++) {
                    JSONObject tempJson = jsonArray.getJSONObject(i);
                    String jsonName = tempJson.getString(SystemJobManager.RunData.getKeyName());
                    if (keyName.equals(jsonName)) {
                        tempJson.put(SystemJobManager.RunData.getValueName(), item.getValue());
                        isFind = true;
                    }
                }
            }
            if (!isFind) {
                JSONObject tempJson = new JSONObject();
                tempJson.put(SystemJobManager.RunData.getKeyName(), keyName);
                tempJson.put(SystemJobManager.RunData.getValueName(), item.getValue());
                jsonArray.add(tempJson);
            }
        }
        JobDataUtil.getInstance().update(entityClass, getJobId(), jsonArray.toString());
    }

    /**
     * 获取所有的运行数据
     *
     * @return json
     * @author jiangzeyin
     */
    public JSONObject getRunDataValueToJSONObject() {
        JSONArray jsonArray = JobDataUtil.getInstance().getJobRunData(entityClass, getJobId());
        return IQuartzInfo.convertJSONObject(jsonArray);
    }

    /**
     * 运行结束
     *
     * @author jiangzeyin
     */
    protected synchronized void putStatus() {
        putStatus(true);
    }


    /**
     * 添加运行状态数据
     *
     * @param isEnd isend
     * @author jiangzeyin
     */
    private synchronized void putStatus(boolean isEnd) {
        String name = getName();
        JobRunResultStatus job = JOB_RUN_RESULT_STATUS_CONCURRENT_HASH_MAP.get(name);
        if (job == null) {
            job = new JobRunResultStatus();
            job.setKey(getKey());
            job.setName(name);
            JOB_RUN_RESULT_STATUS_CONCURRENT_HASH_MAP.put(name, job);
        }
        if (isEnd) {
            job.setRunCount(job.getRunCount() + 1);
            job.setEndTime(System.currentTimeMillis());
        } else {
            job.setContext(context);
            job.setEndTime(null);
        }
    }

    /**
     * 获取调度运行状态
     *
     * @return list
     * @author jiangzeyin
     */
    public static List<JobRunResultStatus> getJobStatus() {
        return new ArrayList<>(BaseJob.JOB_RUN_RESULT_STATUS_CONCURRENT_HASH_MAP.values());
    }

    public String getString(String name, String default_) {
        String value = jobData.get(name);
        if (value == null) {
            return default_;
        }
        return value;
    }

    /**
     * 获取调度运行传入数据
     *
     * @param key      key
     * @param default_ 默认子
     * @return int
     * @author jiangzeyin
     */
    protected int getInt(String key, int default_) {
        String value = jobData.get(key);
        if (value == null) {
            return default_;
        }
        if (value.isEmpty()) {
            return default_;
        }
        return Integer.parseInt(value);
    }

    /**
     * 获取当前调度名称
     *
     * @return name
     * @author jiangzeyin
     * @see IQuartzInfo#getName()
     */
    protected String getName() {
        if (context == null) {
            return "未知名称";
        }
        String name = context.getJobDetail().getJobDataMap().getString("name");
        String systemTag = SystemJobManager.getValue(JobPropertiesInfo.TAG, "");
        name = String.format("%s_%s", name, systemTag);
        return name;
    }

    /**
     * 获取调度数据id
     *
     * @return 数据id
     * @see IQuartzInfo#getId()
     */
    protected int getJobId() {
        return context.getJobDetail().getJobDataMap().getIntValue("id");
    }

    /**
     * 获取调度在程序中唯一的key
     *
     * @return 唯一key
     * @see JobUtil#getJobKeyName(cn.jiangzeyin.entity.IQuartzInfo)
     */
    protected String getKey() {
        return context.getJobDetail().getKey().getName();
    }
}
